package com.ai.bitcoin.schedule;

import com.ai.bitcoin.common.trace.TraceUtil;
import com.ai.bitcoin.constant.Bcc;
import com.ai.bitcoin.redis.service.BccRedisService;
import com.ai.bitcoin.redis.service.RedisLockService;
import com.ai.bitcoin.schedule.task.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

@Component
@Slf4j
public class Schedule {
    private static SimpleDateFormat SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Autowired
    private BccRedisService bccRedisService;
    @Autowired
    private RedisLockService redisLockService;
    @Autowired
    private CurrentPriceTask currentPriceTask;
    @Autowired
    private DetailBasicInfoTask detailBasicInfoTask;
    @Autowired
    private DailyInfoTask dailyInfoTask;
    @Autowired
    private DayPriceTask dayPriceTask;
    @Autowired
    private IndexTask indexTask;
    @Autowired
    private SpanPriceTask spanPriceTask;
    @Value("${taskOpen}")
    boolean taskOpen;
    @Autowired
    RankTask rankTask;
    public String uuid;

    @PostConstruct
    public void init() {
        uuid = UUID.randomUUID().toString();
        log.info("启动，本机uuid:{}", uuid);
    }

    @PreDestroy
    public void clearLock() {
        String[] locks = new String[]{Bcc.BackTask.UPDATE_CURRENT_PRICE};
        log.info("停止服务，清除本地的锁,{}", locks);
        for (String lock : locks) {
            String value = bccRedisService.get(lock);
            if (StringUtils.isNotEmpty(value) && value.contains(uuid)) {
                log.info("清除本地的锁,{}", lock);
                redisLockService.unLock(lock);
            }
        }
    }

    @Scheduled(cron = "0 0/10 * * * ?")
    public void spanPrice() {
        if (!taskOpen) {
            return;
        }
        log.info("spanPriceTask begin:{}", SimpleDateFormat.format(new Date()));
        spanPriceTask.execute();
        log.info("spanPriceTask end:{}", SimpleDateFormat.format(new Date()));
    }

    @Scheduled(cron = "0 0/5 * * * ?")
    public void updateCurrentPrice() {
        log.info("currentPriceTask");
        if (!taskOpen) {
            return;
        }
        TraceUtil.initTrace();
        String lock = Bcc.BackTask.UPDATE_CURRENT_PRICE;
        boolean success = redisLockService.lock(lock, uuid, 120);
        if (success) {
            long start = System.currentTimeMillis();
            log.info("updateCurrentPrice begin:{}", SimpleDateFormat.format(new Date()));
            try {
                currentPriceTask.execute();
            } catch (Exception e) {
                log.info("", e);
            } finally {
                redisLockService.unLock(lock);
            }
            log.info("updateCurrentPrice end:{}", SimpleDateFormat.format(new Date()));
            log.info("execute consume:{}ms", System.currentTimeMillis() - start);

        } else {
            log.info("未获得锁:{}，被其他机器抢先执行了", lock);
        }
    }

    @Scheduled(cron = "0 0/30 0 * * ?")
    public void updateBasicInfo() {
        log.info("detailBasicInfoTask");
        if (!taskOpen) {
            return;
        }
        TraceUtil.initTrace();
        String taskType = Bcc.BackTask.UPDATE_BASIC_INFO;
        boolean success = redisLockService.lock(taskType, uuid, 60 * 5);
        if (success) {
            detailBasicInfoTask.execute();
            redisLockService.unLock(taskType);
        } else {
            log.info("未获得锁:{}，被其他机器抢先执行了", taskType);
        }
    }

    @Scheduled(cron = "0 10 0 * * ?")
    public void updateDailyInfo() {
        log.info("dailyInfoTask");
        if (!taskOpen) {
            return;
        }
        TraceUtil.initTrace();
        String lock = Bcc.BackTask.UPDATE_DAILY_INFO;
        boolean success = redisLockService.lock(lock, uuid, 60 * 5);
        if (success) {
            long start = System.currentTimeMillis();
            log.info("updateDailyInfo begin:{}", SimpleDateFormat.format(new Date()));
            dailyInfoTask.execute();
            log.info("updateDailyInfo end:{}", SimpleDateFormat.format(new Date()));
            log.info("execute consume:{}ms", System.currentTimeMillis() - start);
            redisLockService.unLock(lock);
        }
        else {
            log.info("未获得锁:{}，被其他机器抢先执行了", lock);
        }
    }

    @Scheduled(cron = "0 0 1 * * ?")
    public void dayPrice() {
        log.info("dayPriceTask");
        if (!taskOpen) {
            return;
        }
        TraceUtil.initTrace();
        String lock = Bcc.BackTask.DAY_PRICE;
        boolean success = redisLockService.lock(lock, uuid, 60 * 5);
        if (success) {
            long start = System.currentTimeMillis();
            log.info("dayPrice begin:{}", SimpleDateFormat.format(new Date()));
            dayPriceTask.execute();
            log.info("dayPrice end:{}", SimpleDateFormat.format(new Date()));
            log.info("execute consume:{}ms", System.currentTimeMillis() - start);
            redisLockService.unLock(lock);
        } else {
            log.info("未获得锁:{}，被其他机器抢先执行了", lock);
        }
    }

    @Scheduled(cron = "0 20 0 * * ?")
    public void indexTask() {
        log.info("indexTask");
        if (!taskOpen) {
            return;
        }
        TraceUtil.initTrace();
        String lock = Bcc.BackTask.DAY_PRICE;
        boolean success = redisLockService.lock(lock, uuid, 60 * 5);
        if (success) {
            long start = System.currentTimeMillis();
            log.info("indexTask begin:{}", SimpleDateFormat.format(new Date()));
            indexTask.execute();
            log.info("indexTask end:{}", SimpleDateFormat.format(new Date()));
            log.info("indexTask consume:{}ms", System.currentTimeMillis() - start);
            redisLockService.unLock(lock);
        } else {
            log.info("未获得锁:{}，被其他机器抢先执行了", lock);
        }
    }


    /**
     * 计算分数及排名
     */
    @Scheduled(cron = "0 0 0/1 * * ?")
    public void rank() {
        log.info("rankTask");
        if (!taskOpen) {
            return;
        }
        TraceUtil.initTrace();
        String taskType = Bcc.BackTask.RANK;
        boolean success = redisLockService.lock(taskType, uuid, 60 * 5);
        if (success) {
            rankTask.execute();
            redisLockService.unLock(taskType);
        } else {
            log.info("未获得锁:{}，被其他机器抢先执行了", taskType);
        }
    }
}
